package com.yhy.gateway.utils;

import com.yhy.common.core.result.Result;
import com.yhy.gateway.exception.GlobalErrorWebExceptionHandler;
import lombok.experimental.UtilityClass;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@UtilityClass
public class ResponseUtils {

    public Mono<Void> writeErrorInfo(ServerWebExchange exchange, HttpStatus httpStatus, Throwable ex, Result<?> result) {
        result.setPath(exchange.getRequest().getPath().toString());
        Mono<ServerResponse> responseMono = ServerResponse
                .status(httpStatus).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(result));
        ServerRequest newRequest = ServerRequest.create(exchange, GlobalErrorWebExceptionHandler.messageReaders);
        return RouterFunctions.route(RequestPredicates.all(), (response) -> responseMono).route(newRequest)
                .switchIfEmpty(Mono.error(ex))
                .flatMap((handler) -> handler.handle(newRequest))
                .flatMap((response) -> write(exchange, response));
    }

    /**
     * 参考AbstractErrorWebExceptionHandler
     */
    private Mono<? extends Void> write(ServerWebExchange exchange,
                                       ServerResponse response) {
        exchange.getResponse().getHeaders()
                .setContentType(response.headers().getContentType());
        return response.writeTo(exchange, new ResponseContext());
    }

    /**
     * 参考AbstractErrorWebExceptionHandler
     */
    private class ResponseContext implements ServerResponse.Context {

        @Override
        public List<HttpMessageWriter<?>> messageWriters() {
            return GlobalErrorWebExceptionHandler.messageWriters;
        }

        @Override
        public List<ViewResolver> viewResolvers() {
            return GlobalErrorWebExceptionHandler.viewResolvers;
        }
    }

}
